#include <iostream>
#include <sys/timerfd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>

#include <string>
#include <vector>


//1.创建定时器
// int timerfd_create(int clockid, int flags);
//  clockid: CLOCK_REALTIME-系统实时时间，如果修改了系统时间就会出问题； 
//         : CLOCK_MONOTONIC-从开机到现在的时间是⼀种相对时间；
//  flags: 0-默认是阻塞操作

//linux下一切皆文件，对定时器的操作本质上就是对文件的操作。
//定时器定时的原理是每隔一段时间（定时器的超时时间），系统就会给这个文件描述符对应的定时器写入一个8字节的数据。
//表示从定时事件开始到现在经历了一次超时时间。
//假设定时器设置的定时时间是3s，也就是每隔3s超时1次。
//从启动开始，每隔3s，系统都会给该定时器的文件描述符写入一个1，代表从上一次读取数据到现在超时了1次。
//如果从定时器的文件描述符读取到了10，代表从上一次读取数据到现在超时了10次。

//2.启动定时器
//int timerfd_settime(int fd, int flags, struct itimerspec *new, struct itimerspec *old);
//参数1：返回创建的定时器的文件描述符，
//参数2：0:相对时间，1：绝对时间 。 默认设置为0
//  new： ⽤于设置定时器的新超时时间
//  old： 用来保存原来的超时时间，如果不需要保存原来的超时时间，就设置为nullptr

//  struct itimerspec {
//  struct timespec it_interval; /* 第⼀次之后的超时间隔时间 */
//  struct timespec it_value; /* 第⼀次超时时间 */
//  };
//  struct timespec {
//  time_t tv_sec; /* Seconds */
//  long tv_nsec; /* Nanoseconds */ （纳秒）
//  };

//解析：如果设置第一次超时时间it_value为3s，则过去3s后，向定时器的fd写入一个8字节数据表示第一次超时。
//往后的超时时间间隔都按照it_interval（参数1）超时间隔来。

int main()
{
    //1.创建定时器
    int timerfd = timerfd_create(CLOCK_MONOTONIC,0);
    if(timerfd < 0)
    {
        perror("timerfd create fail\n");
        return -1;
    }
    itimerspec itime;
    itime.it_value.tv_sec = 2; //第一次超时时间
    itime.it_value.tv_nsec =0;

    itime.it_interval.tv_sec = 1 ;//往后每次超时间隔时间
    itime.it_interval.tv_nsec =0;
    //2.启动定时器
    timerfd_settime(timerfd,0, &itime,nullptr);

    while(1)
    {
        uint64_t times;//超时次数 （必须一次要读取的数据大小是8字节，不能用int）
        //sleep(10);
        int ret = read(timerfd,&times,8); //默认阻塞读取，直到有数据到来
        //只要有数据进来，马上读走，所以每次都会显示超时1次。
        if(ret < 0)
        {
            perror("read error:");
            return -1;
        }
        printf("超时了，超时了%ld次\n",times);// 1 1 1
    }
    
    close(timerfd);
    return 0;
}